/*	$Id: if_loop.c 6 2008-07-29 02:30:10Z phrakt $	*/
/*
 * Copyright (c) 2003 Jean-Francois Brousseau <jfb@openbsd.org>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHLOOP IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
/*
 * Loopback interface
 */

#include <sys/param.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/socket.h>

#if defined(__OpenBSD__) || defined(__NetBSD__)
#include <net/if.h>
#include <net/if_dl.h>
#include <net/if_types.h>

#elif defined(__linux__)
#include <net/if_arp.h>
#endif

#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

#include "if.h"
#include "pkt.h"
#include "dlink.h"
#include "pforge.h"


#define PFIF_LOOP_MINFRAMELEN    64   /* minimum frame length */
#define PFIF_LOOP_MAXFRAMELEN  1518   /* max frame length with hdr and crc */

#define PFIF_LOOP_HDRLEN          4

#define PFIF_LOOP_MAXMTU (PFIF_LOOP_MAXFRAMELEN - PFIF_LOOP_HDRLEN)
#define PFIF_LOOP_MINMTU (PFIF_LOOP_MINFRAMELEN - PFIF_LOOP_HDRLEN)


int  pfif_loop_init   (void);
int  pfif_loop_create (PF_NETIF *);
int  pfif_loop_input  (PF_NETIF *, PF_PKT *);
int  pfif_loop_output (PF_NETIF *, PF_PKT *);
void pfif_loop_print  (PF_NETIF *, PF_PKT *);


struct pfif_loop_hdr {
	uint32_t  lh_type;

};


static const char *pfif_loop_addrfam[] = {
	"AF_UNSPEC",
	"AF_LOCAL",
	"AF_INET",
	"AF_IMPLINK",
	"AF_PUP",
	"AF_CHAOS",
	"AF_NS",
	"AF_ISO",
	"AF_ECMA",
};



struct pf_netif_ops pf_loop_ops = {
	pfif_loop_init,
	NULL,
	pfif_loop_create,
	NULL,
	pfif_loop_input,
	pfif_loop_output,
	NULL,
	pfif_loop_print
};




/* protocol IDs of the upper layers for each family */
int pfif_loop_ipid = -1;



/*
 * pfif_loop_init()
 *
 * Initialization routine for the
 */
int
pfif_loop_init(void)
{
	return (0);
}


int
pfif_loop_create(PF_NETIF *ifp)
{
	int sock;
	struct ifreq ifr;

	sock = socket(AF_INET, SOCK_STREAM, 0);
	if (sock == -1) {
		return (-1);
	}

	strlcpy(ifr.ifr_name, ifp->if_name, sizeof(ifr.ifr_name));

	if (ioctl(sock, SIOCIFCREATE, &ifr) == -1) {
		return (-1);
	}

	return (0);
}


/*
 * pfif_loop_input()
 *
 * Input routine to read loopback frames and decapsulate the loopback layer.
 */
int
pfif_loop_input(PF_NETIF *ifp, PF_PKT *pkt)
{
	uint8_t buf[PFIF_LOOP_MAXFRAMELEN];
	ssize_t len;
	struct pfif_loop_hdr *hdr;

	switch (hdr->lh_type) {

	}

	return (0);
}


/*
 * pfif_loop_output()
 *
 * Output routine for loopback virtual interfaces.
 */
int
pfif_loop_output(PF_NETIF *ifp, PF_PKT *pkt)
{
	uint8_t buf[PFIF_LOOP_MAXFRAMELEN];
	size_t left, framelen;
	struct pfif_loop_hdr *hdr;

	hdr = (struct pfif_loop_hdr *)buf;

	return (0);
}


/*
 * pfif_loop_print()
 *
 * Print a human-readable version of the data contained in an loopback header.
 */
void
pfif_loop_print(PF_NETIF *ifp, PF_PKT *pkt)
{
	uint32_t type;
	struct pfif_loop_hdr *hdr;

	type = ntohl(hdr->lh_type);

	printf("Loopback:  AF=%s\n", pfif_loop_addrfam[type]);
}
